<?php
/*=============================================================================
|| ##################################################################
||	phpFoX Konsort
|| ##################################################################
||
||	Copyright		: (C) 2005-2007 PHPFOX Limited a Reality Fox Creation
||	Contact			: info@phpfox.com
||
||	- phpFoX and all of its source code and files are protected by Copyright Laws.
||
||	- The license for phpFoX permits you to install this software on a single domain (.com, .org, .net, etc.).
||
||	- You may also not remove this copyright screen which shows the copyright information and credits for phpFoX (RealityFOX Creations).
||
||	- phpFoX Konsort is NOT a FREE software - http://www.phpfox.com/license/
||
|| ##################################################################
=============================================================================*/

/* $File: ./include/modules/Account/classes/PhpFox_ServiceSecurity.class.php, $Author:  $ */

/** Base security-related service:
 * - login/logout/check current user
 * - forgot password (create/send new password, set as current)
 * - membership/permissions
 * - staff permissions
 *
 * @package module.account
 * @version $Id: PhpFox_ServiceSecurity.class.php 482 2008-08-15 11:29:00Z phpfoxsv $
 *
 */
class PhpFox_Mod_Account_ServiceSecurity extends BaseService
{
    /** Returns current user or null if not logged in
     * @return PhpFox_Mod_Account_ItemAccount
     */

    function onChangePassword($oAccount)
    {
        if(PHPFOX_VB)
        {
            App::plugin_changePassword($aParam['Account']);
        }
    }

    function csrfInput()
    {
    	if (!App::getParam('csrf_enabled')) 
    	{
    		return;
    	}
    	
    	$sHash = $this->hashEncode(session_id() . md5(App::getParam('csrf_hash')));	
    	return '<div><input type="hidden" name="input_site_token" value="' . $sHash . '" /></div>' . "\n";
    }
    
    function csrfCheck()
    {
    	if (!App::getParam('csrf_enabled')) 
    	{
    		return;
    	}
    	
    	if (isset($_POST['input_site_token']) && !$this->hashCheck((session_id() . md5(App::getParam('csrf_hash'))), $_POST['input_site_token'])) 
    	{
    		exit('CSRF Attack!');
    	}
    }
    
	/**
	 * Create a random MD5() Hash
	 * @access public
	 * @param	string	$password is the pass phrase we need to hash
	 * @return	string	Hashed
	 */
	function hashEncode($password)
	{
		$seed = '';
		for ($i = 1; $i <= 8; $i++)
		{
			$seed .= substr('0123456789abcdef', rand(0,15), 1);
		}
		return md5($seed . $password) . $seed;
	}

	/**
	 * Checks if a hashed value is matching up from what we got using self::hashEncode
	 * @access public
	 * @see self::hashEncode
	 * @param	string	$password	is the password
	 * @param	string	$stored_valued	is the hashed value of the $password
	 * @return 	bool	Checks if hash is correct
	 */
	function hashCheck($password, $stored_value)
	{	
		$stored_seed = substr($stored_value, 32, 8);
		return ((md5($stored_seed.$password).$stored_seed == "{$stored_value}") ? true : false);
	}    
    
    function &getCurrentUser()
    {
    	static $oAcc = 0;

    	if ( $oAcc )
    	{
			return $oAcc;
    	}

		$oAcc = $this->_oModule->getItem('Account');

		if(isset($_COOKIE['phpfox_id']) && isset($_COOKIE['phpfox_h']))
		{
			$iAccId = intval($_COOKIE['phpfox_id']);

			$sPassHash = base64_decode($_COOKIE['phpfox_h']);

        	$oAcc->aData = $this->oDatabase->getRow("SELECT * FROM `". App::getT('user') ."` WHERE `id` ='". $iAccId ."'");

			if ( !empty($oAcc->aData['id']) && $sPassHash )
            {
            	if ( !$this->_loginAddCheck($oAcc) )
                {
                	$oAcc = null; //failed on addtional checks - reset user to null
				}				
            	elseif (md5(md5($oAcc->aData['password']) . $oAcc->aData['signup']) != $sPassHash)
                {
					$oAcc = null;
				}				
			}
			else
            {
				$oAcc = null;
			}
		}		
        elseif ($this->_oModule->hasSessVar('phpfox_id'))
        {
        	$sPassHash = base64_decode($this->_oModule->getSessVar('phpfox_h'));

        	$oAcc->aData = $this->oDatabase->getRow("SELECT * FROM `". App::getT('user') ."` WHERE `id` ='". intval($this->_oModule->getSessVar('phpfox_id')) ."'");

            if ( !empty($oAcc->aData['id']) && $sPassHash )
            {
            	if ( !$this->_loginAddCheck($oAcc) )
                {
                	$oAcc = null; //failed on addtional checks - reset user to null
				}
				elseif (md5(md5($oAcc->aData['password']) . $oAcc->aData['signup']) != $sPassHash)
                {
					$oAcc = null;
				}
            }
            else
            {
                $oAcc = null; //no such user in db - reset user to null
            }
		}

	    if (!isset($oAcc->aData['id']))
        {
            $oAcc = null;
        }

        if ($oAcc && (!$this->_oModule->getSessVar('by_admin', false) && $oAcc->aData['is_banned']))
        {
            $oAcc = null;
        }

        if ($oAcc)
        {
            $this->_checkExpire($oAcc);
        }

        return $oAcc;
    }

    /** Try user login: check login,
     *  set new login session variables: login flag (user ID).
     * @param string $sLogin    user login
     * @param string $sPassword user password
     * @param string $aStatuses statuses eligeble to login
     * @return bool true - login ok, false - error
     * @see _loginAddCheck()
     */
    function login($sLogin, $sPassword, $sUserType='', $bRemember=false)
    {
        $oAcc = &$this->_oModule->getItem('Account');
        /* @var $oAcc PhpFox_Mod_Account_ItemAccount */

        $sCond = 'user = "'.$oAcc->oDb->escape($sLogin).'"';

        // Check one more time that this is user is valid
        if ($oAcc->loadByCondition($sCond)) //user account exists
        {
            //check password
            if ( !App::pluginInstalled('vbulletin') )
            {
            	if ($oAcc->aData['password'] != md5($sPassword))
            	{
            	    $this->_addError('Mod_Account.error.login.pass');
            	}
            }

            // Check if the user has been banned
            if ($oAcc->aData['is_banned'])
            {
                $this->_addError('Mod_Account.user_banned');
            }
            
			
            if (!$this->aErrors)
			{

                if ($this->_loginAddCheck($oAcc))
                {
                	$oLog = App::getModuleService('Log', 'Log');
                	$aUserSession = $oLog->getUserSession();
                	$this->oDatabase->_delete(App::getT('online_session'), "online_session_id = '". $oAcc->oDb->escape($aUserSession['online_session_id']) ."'");
                	$this->oDatabase->_delete(App::getT('online_session'), "online_session_user = '". $oAcc->oDb->escape($oAcc->aData['user']) ."'");
                	
                	App::unsetSession('used_space');

                	// Set cookies if they used the "remember me option"
                    if ($bRemember)
                    {
                        setcookie('phpfox_id', $oAcc->aData['id'], (time()+3600*24*365), '/');
                        setcookie('phpfox_h', base64_encode(md5(md5($oAcc->aData['password']) . $oAcc->aData['signup'])), (time()+3600*24*365), '/');
                    }
                    else
                    {
                    	setcookie('phpfox_id', $oAcc->aData['id'], 0, '/');
                    	setcookie('phpfox_h', base64_encode(md5(md5($oAcc->aData['password']) . $oAcc->aData['signup'])), 0, '/');
                    }

					setcookie("cssName","","-1","/");
					setcookie("cssFile","","-1","/");
					setcookie("cssLayout","","-1","/");

                    // Set default sessions
                    $this->_oModule->setSessVar('phpfox_id', $oAcc->aData['id']);
                    $this->_oModule->setSessVar('phpfox_h', base64_encode(md5(md5($oAcc->aData['password']) . $oAcc->aData['signup'])));
                    $this->_oModule->setSessVar('by_admin', false);
                    
                    unset($_SESSION['phpFox']['sRandId']);

                    //update `login`,`login_ip`
                    $oAcc->aData['login']       = time();
                    $oAcc->aData['login_ip']    = $_SERVER['REMOTE_ADDR'];
                    $oAcc->aData['new_pass'] = '';
                    $oAcc->update(array('login', 'login_ip', 'new_pass'));

                    // Update the total space a user is using
			        $oAccountService = &App::getModuleService('Account', 'Account');
			        $oAccountService->getUsedSpace($oAcc->aData['user'], false, $oAcc->aData['id'], true);

                    // Update the users points
                    $oAccountService->getPoints($oAcc);

                    // @PLUGIN // Login routine
                    App::plugin_loginUser($oAcc);

                    // Check if a user has expired
                    $this->_checkExpire($oAcc);
                }
            }
        }
        else
        {
            $this->_addError('Mod_Account.error.login');
		}

        return !$this->aErrors;
    }

    /** Login admin as selected user (snoop member)
     *
     *
     * @param int $iUserId user account ID
     */
    function loginByAdmin($iUserId)
    {
    	$aItem = $this->oDatabase->getRow("SELECT id, user, password, signup FROM ". App::getT('user') ." WHERE id = '". $iUserId ."'");
    	setcookie('phpfox_id', $aItem['id'], 0, '/');
		setcookie('phpfox_h', base64_encode(md5(md5($aItem['password']) . $aItem['signup'])), 0, '/');
		$this->_oModule->setSessVar('phpfox_id', $aItem['id']);
        $this->_oModule->setSessVar('phpfox_h', md5(md5($aItem['password']) . $aItem['signup']));
		$this->_oModule->setSessVar('by_admin', true);

		$oAccountService = &App::getModuleService('Account', 'Account');
		$oAccountService->getUsedSpace($aItem['user'], false, $aItem['id'], true);
		
		if (isset($_SESSION['local_points'])) 
		{
			unset($_SESSION['local_points']);	
		}
		
		$oAcc = &$this->_oModule->getItem('Account');
		$oAcc->loadByCondition("id = '". $iUserId ."'");
		$oAccountService->getPoints($oAcc);

        return true;
    }

    /** Get current user login name (field user)
     *
     *
     * @return string user name or empty string if user not logged in
     */
    function getCurrentUserLogin()
    {
        $oAcc = $this->getCurrentUser();
        return ($oAcc ? $oAcc->aData['user'] : '');
    }

    /** Get user acconut object by user name
     *
     * @param string $sName username
     * @return PhpFox_Mod_Account_ItemAccount user account or null if no account found
     */
    function getUserByName($sName)
    {
       $sName = Database::escape($sName);
       $oAcc = $this->_oModule->getItem('Account');
       /* @var $oAcc PhpFox_Mod_Account_ItemAccount */

       if ($oAcc->loadByCondition('user = "'.$sName.'"'))
       {
	       return $oAcc;
       }

	   return null;
    }
    
    function getAdminName()
    {
       $oAcc = $this->_oModule->getItem('Account');
       /* @var $oAcc PhpFox_Mod_Account_ItemAccount */
       if ($oAcc->loadByCondition('type = 0'))
       {
	       return $oAcc->aData['user'];
       }
	   return null;
    }

    /**
     * Get user id by username
     *
     * @param string $sName username
     * @return integer user id
     *
     */
    function getUserIdByName($sName)
    {
        $oAcc = $this->getUserByName($sName);
        if ($oAcc)
        {
            return $oAcc->aData['id'];
        }
        return null;
    }

    /** Performs additional checks
     * 1. user.verify <> 1
     *
     * @return bool true - additional checks fails, false - otherwise
     */
    function _loginAddCheck(&$oAcc)
    {
        if (!$this->_oModule->getSessVar('by_admin'))
        {
            //checks for non-snoop logins
            if (1 == $oAcc->aData['verify'])
            {
                $this->addErrors(App::format('Mod_Account.error.login.not_activated'));
                return false;
            }
        }
        return true;
    }

    /** Performs logout
     */
    function logout()
    {
        $oUser = $this->getCurrentUser();       
        if ($oUser)
        {
            $this->callback($this, 'logout', array('oUser'=>$oUser));
            App::plugin_logoutUser($oUser);
        }
        $this->_oModule->unsetSessVar('phpfox_id');
        $this->_oModule->unsetSessVar('phpfox_h');
        App::unsetSession('used_space');

        setcookie('phpfox_id',  -1, time() - 1, '/');
        setcookie('phpfox_h',   '', time() - 1, '/');

		setcookie("cssName", '', -1, "/");
		setcookie("cssFile", '', -1, "/");
		setcookie("cssLayout", '', -1, "/");
		
		unset($_SESSION['phpFox']['sRandId']);
		
		if (isset($_SESSION['temp_lang_id']))
		{
			unset($_SESSION['temp_lang_id']);
		}
		
		if (isset($_SESSION['local_points'])) 
		{
			unset($_SESSION['local_points']);	
		}
    }

    /** Get user role by given field values
     * @param int $iType   type value
     * @param int $iAdmin  admin value
     * @return  string user type
     */
    function getRoleByFields($iType, $iAdmin)
    {
        if ($iType == 0)
        {
            return (!$iAdmin) ? 'admin' : 'staff';
        }
        return 'member';
    }

    /** Is given user admin (not staff)
     *
     * @see isStaff()
     * @param string $sUserName
     * @return bool
     */
    function isAdmin($oAcc = null)
    {
        return (App::getParam('Mod_Account.membership.admin') == $this->getMembership($oAcc));
    }

    /** Is given user staff (or admin)
     *
     * @see isAdmin()
     * @param string $sUserName
     * @return bool
     */
    function isStaff($oAcc = null, $bOnlyStaff = false)
    {
        $aMemberships = array
        (
            App::getParam('Mod_Account.membership.staff'),
        );
        if (!$bOnlyStaff)
        {
            $aMemberships[] = App::getParam('Mod_Account.membership.admin');
        }

        return (in_array($this->getMembership($oAcc), $aMemberships));
    }

    /** Return membership for given user
     */
    function getMembership(&$oAcc)
    {
        if (!$oAcc)
        {
            $oAcc = &$this->getCurrentUser();
        }

		if ( !isset($oAcc->aData['type']) )
		{
			return App::getParam('Mod_Account.membership.guest');
		}

        return ($oAcc ? $oAcc->aData['type'] : App::getParam('Mod_Account.membership.guest'));
    }

    /** Returns membership name by type.
     *
     * @param int $iType membership type
     * @return string membership name
     */
    function getMembershipName($iType)
    {
    	static $sName;

    	if ( isset($sName[$iType]) )
    	{
    		return $sName[$iType];
    	}

        $oDb = Database::get();
        /* @var $oDb Database */
        $sName[$iType] = $oDb->getField('SELECT title FROM '.App::getT('membership').
                                '  WHERE membership_id = '.intval($iType));
        return $sName[$iType];
    }

    /** Returns membership data.
     *
     * @param int $iType membership type
     * @return string membership name
     */
    function getMembershipData($iMembershipId)
    {
   		static $details;

   		if ( isset($details[$iMembershipId]) )
		{
			return $details[$iMembershipId];
		}

		$oCache = &App::newObject("Cache");
    	$oCache->setFile("membership". $iMembershipId .".php");
    	if ( $oCache->isCached() )
    	{
    	 	$oCache->doRequire();
    	 	$details[$iMembershipId] = $oCache->details;
    	}
    	else
    	{
			$details[$iMembershipId] = $this->oDatabase->getRow('SELECT mem.membership_id, mem.is_special, mem.img, mem.title, mem.descr, mem.price, mem.pay_type, mem.max_upload, mem.max_inbox, mem.is_internal, mem.no_ads, mem.allow_block, mem.design_tool, mem.pos FROM `'. $this->oDatabase->getT('membership') .'` AS mem WHERE membership_id="'. $iMembershipId .'"');
			$content = "<?php\n";
			foreach($details[$iMembershipId] as $aRow => $value)
			{
				$content .= '$this->details[\''. $aRow .'\'] = "'. $oCache->cleanFile($value) .'";'."\n";
   			}
   			$content .= "?>";
   			$oCache->createCached($content);
		}

		return $details[$iMembershipId];
	}


    /** Get users's membership data
     *
     * @param PhpFox_Mod_Account_ItemAccount $oAcc user's object
     *
     */
    function getUserMembershipData($oAcc = null)
    {
        if (!$oAcc)
        {
            //try to get current user
            $oAcc = $this->getCurrentUser();
        }
		
        $iMembershipId = (($oAcc && isset($oAcc->aData['type'])) ? $oAcc->aData['type'] : App::getParam('Mod_Account.membership.guest'));
        
        return $this->getMembershipData($iMembershipId);
    }



    /** Creates and send new password for user with given url
     *
     * @param string $sEmail user email
     * @return bool true - created and sended ok, false - error occured
     */
	function sendNewPass($sEmail, $ConfitmPage)
	{
		$oAcc = &$this->_oModule->getItem('Account');
		if ($oAcc->loadByCondition('email = "'.$sEmail.'"'))
		{
			$oAcc->aData['new_pass'] = $this->_generateNewPass();
			$oAcc->update(array('new_pass'));
			$oMailer = App::newObject('mail_Mailer');
			/* @var oMailer mail_Mailer */
			$sUrl = App::makeUrl($ConfitmPage, array('id'  => $oAcc->aData['id'], 'hash' => md5($oAcc->aData['new_pass'])));
			$aVars = array(
				'SITENAME' => App::getSetting('site_name'),
				'USERNAME' => $oAcc->aData['user'],
			    'URL' => $sUrl,
			);

			$oMailer->send('email_lost_password_verify', $sEmail,App::format('core.lost.password'), $aVars);
			return true;
		}
		else
		{
		    $this->addErrors(App::format('Mod_Account.error.no_such_user'));
		}

		return false;
	}


	/** Generate random pass
	 */
	function _generateNewPass($iLength = 12)
	{
		$iLength = ($iLength < 2) ? 2 : $iLength;
		$aLetters = range('a', 'z');
		$aDigits  = range(1, 9);
		$sPass = $aLetters[array_rand($aLetters)].$aDigits[array_rand($aDigits)];
		$aSymbols = (array_merge($aLetters, $aDigits));
		for($i = 2; $i < $iLength; $i++)
		{
			$sPass .= $aSymbols[array_rand($aSymbols)];
		}
		return $sPass;
	}

	/**  Verify and approve new password
	 *
	 * @param int    $iAccId       account ID
	 * @param string $sNewPassHash new password hash
	 */
	function verifyNewPass($iAccId, $sNewPassHash)
	{
		$oAcc = &$this->_oModule->getItem('Account');
		if ($oAcc->load(intval($iAccId)))
		{
			if ($oAcc->aData['new_pass'] && ($sNewPassHash==md5($oAcc->aData['new_pass'])))
			{
				$sPass = $oAcc->aData['new_pass'];
				$sEmail = $oAcc->aData['email'];
				$oAcc->aData['password'] = md5($sPass);
				$oAcc->aData['new_pass'] = '';
				if ($oAcc->update(array('password')))
				{
					$oMailer = App::newObject('mail_Mailer');
					$aVars = array(
						'SITENAME' => App::getSetting('site_name'),
						'HOME'     => App::getParam('url'),
						'USERNAME' => $oAcc->aData['user'],
						'PASSWORD' => $sPass,
					);

					phpFoXPlugins::call_phpfox_function('update_password',array($iAccId,$sPass));
					$oMailer->send('email_lost_password', $sEmail, App::format('core.lost.password'), $aVars);
					return true;
				}
			}
			else
			{
				$this->addErrors('Wrong data');
			}
		}
		else
		{
			$this->addErrors('No Such account');
		}

		return false;
	}

	/** Check entered protection code against stored in session (by generated picture)
	 *
	 * @see PhpFox_Mod_Account_ComponentRandomImage
	 * @param string $sCode protectin code to test
	 * @return true - code ok, false - code wrong (empty or not equal to stored in session)
	 */
	function checkProtectionCode($sCode)
	{
	    $oLog =& App::getModuleService('Log', 'Log');	
		$oDb =& Database::get();
		$iId = $oLog->getUserSession();
	    $aRow = $oDb->getRow("SELECT captcha_id, imagehash FROM " . App::getT('captcha') . " WHERE captcha_id = '" . $iId . "' AND imagehash = '" . md5(md5($sCode) . $iId) . "'");	    
	    if (isset($aRow['imagehash'])) 
	    {
			$oDb->_delete(App::getT('captcha'), "captcha_id = '" . $aRow['captcha_id'] . "' AND imagehash = '" . $aRow['imagehash'] . "'");
	    	return true;
	    }	    
	    return false;
	}

	function setupNewMembership()
	{
		$aValFields = array();

		$oReq = &App::getRequest();
		$aGetItems = $oReq->getArray('aMemb');
	    $aMemberships = array((count($aGetItems) ? $aGetItems : ''));

		$aCondModule = array('type' => ' = ""');
	   	$aModulePerms = &$this->getModulePerms($aCondModule);
	    $aModuleType = $this->oDatabase->getRows("SELECT id, name FROM ". App::getT('module_type') ." ORDER BY id DESC");

	    foreach($aMemberships as $k => $v)
	    {
            $aMemberships[$k]['perms'] = $aModulePerms;

			foreach($aModuleType as $iType => $aType)
			{
				$aType['temp'] = App::format('Mod_Account.header.' . $aType['name']);
				$aMemberships[$k]['extra'][$iType] = $aType;
				$aCondModuleType = array('type' => ' = "'. $aType['id'] .'"');

    			$aModulePermsType = &$this->getModulePerms($aCondModuleType);

				foreach($aModulePermsType as $iPermIdType => $aPermType)
				{
					$aPermType['val'] = (isset($aMemPerms[$iPermIdType]) ? $aMemPerms[$iPermIdType]['val'] : '');
					$aMemberships[$k]['extra'][$iType]['items'][$iPermIdType] = $aPermType;
					if ( isset($aPermType['def']) )
					{
						$aValFields['aPerm['. $iPermIdType .']'] = array('title' => $aPermType['perm_name'], 'def' => ''. $aPermType['def'] .'');
					}
               	}
			}
	    }

		return array($aMemberships, $aValFields);
	}

	/** Get memberships list
	 *
	 * @return array memberships info
	 */
	function getMembershipsList($aCond = array())
	{
		$aValFields = array();

	    $oMembership = &$this->_oModule->getItem('Membership');
	    /* @var $oMembership PhpFox_Mod_Account_ItemMembership */

	    list($aMemberships) = $oMembership->getList($aCond, 0, 0, 'pos, membership_id');

		$aCondModule = array('type' => ' = ""');
	    $aModulePerms = &$this->getModulePerms($aCondModule);

	    $aModuleType = $this->oDatabase->getRows("SELECT id, name FROM ". App::getT('module_type') ." GROUP BY name ORDER BY id DESC");

	    foreach($aMemberships as $k => $v)
	    {
	        if (!$v['is_internal'])
	        {
	            $aMemberships[$k]['perms'] = $aModulePerms;
	            
	            $aMemberships[$k]['pay_type'] = ((strtolower($aMemberships[$k]['pay_type']) == 'monthly') ? 'monthly' : 'onetime');

                $aMemPerms = $this->getMembershipPerms($v['membership_id']);

                foreach($aModulePerms as $iPermId => $aPerm)
                {
					if (!is_array($aPerm['vals']))
					{
						continue;
					}
                	
                	if (isset($aMemPerms[$iPermId]))
                    {
                        $aMemberships[$k]['perms'][$iPermId]['val'] = $aMemPerms[$iPermId]['val'];
                    }
                    else
                    {
                        $aMemberships[$k]['perms'][$iPermId]['val'] = 'no';
                    }
                                        
                    //restrict permissions set for guest
        	        if (App::getParam('Mod_Account.membership.guest') == $v['membership_id'])
        	        {
        	        	$aMemberships[$k]['perms'][$iPermId]['vals'] = array(
        	                'no'        => App::format('Mod_Account.perm_val.no'),
                            'read_only' => App::format('Mod_Account.perm_val.read_only'),
                        );
        	        }
                }

				foreach($aModuleType as $iType => $aType)
				{
					$aType['temp'] = App::format('Mod_Account.header.' . $aType['name']);
					$aMemberships[$k]['extra'][$iType] = $aType;
					$aCondModuleType = array('type' => ' = "'. $aType['id'] .'"');

	    			$aModulePermsType = &$this->getModulePerms($aCondModuleType);

	    			foreach($aModulePermsType as $iPermIdType => $aPermType)
                	{
                		$aPermType['val'] = (isset($aMemPerms[$iPermIdType]) ? $aMemPerms[$iPermIdType]['val'] : '');
						$aMemberships[$k]['extra'][$iType]['items'][$iPermIdType] = $aPermType;
						if ( isset($aPermType['def']) )
						{
							$aValFields['aPerm['. $iPermIdType .']'] = array('title' => $aPermType['perm_name'], 'def' => ''. $aPermType['def'] .'');
						}
                	}
				}
	        }
	    }	    

	    return array($aMemberships, $aValFields);
	}

	/** Get module permissions list
	 *
	 * @return array module permissions info
	 */
	function &getModulePerms($aCondModule = array())
	{
		$oModulePerm = &$this->_oModule->getItem('ModulePerm');
    	/* @var $oModulePerm PhpFox_Mod_Account_ItemModulePerm */
      	list($aModulePerms) = $oModulePerm->getList($aCondModule, 0, 0, '', array(), 'module_perm_id', '', array(), 'mp.code');

	    foreach($aModulePerms as $k => $v)
	    {
	        $aModulePerms[$k]['perm_name'] = App::format('Mod_Account.perm.'.$aModulePerms[$k]['code']);
			if ( !eregi(",", $v['vals']) )
			{
				continue;
			}
	        $aRawVals = explode(',',$v['vals']);
	        $aVals = array();
	        foreach($aRawVals as $k1 => $v1)
	        {
	            $aVals[$v1] = App::format('Mod_Account.perm_val.'.$v1);
	        }
	        $aModulePerms[$k]['vals'] = $aVals;
	    }
	    return $aModulePerms;
	}

	/** Get permissions values for membership
	 * @param int $iMembershipId membership ID
	 */
	function &getMembershipPerms($iMembershipId)
	{
		static $aMemPerms;

		if (isset($aMemPerms[$iMembershipId]))
		{
			return $aMemPerms[$iMembershipId];
		}

	    $oDb = &Database::get();
	    /* @var $oDb Database */
	    $sSql = 'SELECT * FROM '.App::getT('memb2perm').
	            '  WHERE membership_id = '.intval($iMembershipId);
	   	$aMemPerms[$iMembershipId] = $oDb->getRows($sSql, true, 'module_perm_id');

	   	return $aMemPerms[$iMembershipId];
	}

	/** Updates membership
	 * @param array $aMembership membership data
	 * @param array $aPerms      permissions data
	 * @return bool true - update ok, false - error occured
	 */
	function updateMembership($aMembership, $aPerms)
	{
	    $oMembership = $this->_oModule->getItem('Membership');
	    /* @var $oMembership PhpFox_Mod_Account_ItemMembership */

	    //update membership
	    $oMembership->setData($aMembership);
	    $oMembership->update();
	    //update permissions
        $oMembership->oDb->query('DELETE FROM '.$this->oDatabase->getT('memb2perm').
                                 '  WHERE membership_id = '.$oMembership->aData[$oMembership->sId]);
        $aVals = array(
        	'membership_id' => $oMembership->aData[$oMembership->sId],
        );
        foreach($aPerms as $k=>$v)
	    {
	        $aVals['module_perm_id'] = $k;
	        $aVals['val']            = $v;
	        $oMembership->oDb->insert(App::getT('memb2perm'), $aVals);
	    }
	    return true;
	}

	/** Create new membership
	 *
	 * @param array  $aMembership membership data
	 * @param array  $aPerms      permissions data
	 * @param string $sImageField image field name
	 * @return int membership ID, or false on error
	 */
	function createMembership($aMembership, $aPerms)
	{
	    $oMembership = $this->_oModule->getItem('Membership');
	    /* @var $oMembership PhpFox_Mod_Account_ItemMembership */
	    
	    $aRow = $oMembership->oDb->getField("SELECT membership_id FROM " . App::getT('membership') . " ORDER BY membership_id DESC LIMIT 1");
	    $aMembership['membership_id'] = ($aRow + 1);

	    //update membership
	    $oMembership->setData($aMembership);
	    $oMembership->insert();
	    if ($aMembership['membership_id'])
	    {
    	    //add permissions
            $aVals = array(
            	'membership_id' => $oMembership->aData[$oMembership->sId],
            );
            foreach($aPerms as $k=>$v)
    	    {
    	        $aVals['module_perm_id'] = $k;
    	        $aVals['val']            = $v;
    	        $oMembership->oDb->insert(App::getT('memb2perm'), $aVals);
    	    }
	    }
	    return $aMembership['membership_id'];
	}

	/** Deletes membership
	 *
	 * @param int $iMembershipId membership ID
	 * @return bool true - membership succesfully deleted, false - error occured
	 */
	function deleteMembership($iMembershipId)
	{
	    $oMemb = $this->_oModule->getItem('Membership');
	    //check membership existence and type (is special)
	    if (!$oMemb->load($iMembershipId) || $oMemb->aData['is_special'])
	    {
	        return false;
	    }

	    //reset all corresponding members to normal
        $aVals = array('type' => App::getParam('Mod_Account.membership.normal'));
        $oMemb->oDb->update($this->oDatabase->getT('user'), $aVals, "`type` = ".$oMemb->getId());

        //delete permissions
        $oMemb->oDb->query('DELETE FROM '.$this->oDatabase->getT('memb2perm').' WHERE membership_id = '.$oMemb->getId());

        //delete membership
        $oMemb->delete($oMemb->getId());

        return true;
	}


    /** Checks, that area with synonim $sPermCode has access and redirects
     *  to error page if false
     * @param string      $sPermCode area synonim
     * @param string|array $mPerms   possible permission values
     * @param boolean $bExit redirect to deny page
     * @return bool
     */
	function checkPerm($sPermCode, $mPerms, $bExit = true)
	{
	    if (!is_array($mPerms))
	    {
	        $mPerms = array($mPerms);
	    }

	    $sPerm = $this->getPerm($sPermCode);

	    if (!in_array($sPerm, $mPerms))
	    {
	        if ($bExit)
	        {
	            if (!$this->getCurrentUserLogin())
	            {
	                App::gotoUrl('public.login',  array('members' => 'only'));
	            }
	            App::gotoUrl('public.account.membership');
	        }
	        else
	        {
	            return false;
	        }
	    }

	    return true;
	}

	function checkPermStatus($sSectionName,$sPermName)
	{
		if ( !App::getSetting($sSectionName) && $this->getPerm($sPermName) != 'no' )
		{
			return true;
		}
		return false;
	}

	/** Return permission value for given user's membership
	 * (or default value if user account is null or no such permission
	 *  found in membership)
	 * If no user object passed then crrent user will be used. If no current
	 * user then guest membership will be used.
	 *
	 * @param string                         $sPermCode  permission's code
	 * @param string                         $sDef       default value (by default 'no')
	 * @param PhpFox_Mod_Account_ItemAccount $oAcc       user account object (by default current user)
	 * @return string permission value
	 */
	function getPerm($sPermCode, $sDef = 'no', $oAcc=null)
	{
		static $aPerms;
		static $aRows;

    	if (!$oAcc)
    	{
    	    //try to load current user
    	    $oAcc = &$this->getCurrentUser();
    	}
		
		if ( $oAcc )
		{
			if ( isset($oAcc->aData['type']) && ($oAcc->aData['type'] == '0' || $oAcc->aData['type'] == '1') )
			{
				return 'full';
			}
		}

		$iType = (($oAcc && !empty($oAcc->aData['type'])) ? $oAcc->aData['type'] : App::getParam('Mod_Account.membership.guest'));
	
    	if (!isset($aPerms[$iType])) //not in cache yet
    	{
    	 	$aPerms = $this->cachePermDetails($iType);
   		}

	 	return isset($aPerms[$iType][$sPermCode]) ? $aPerms[$iType][$sPermCode] : $sDef;
	}

	function cachePermDetails($iType)
	{
		$oCache = &App::newObject("Cache");
		$oCache->setFile("memb2perm". $iType .".php");

		if ( !$oCache->isCached() )
	   	{
	   		$iCnt = $this->oDatabase->getField('SELECT COUNT(*) FROM
				'. $this->oDatabase->getT('memb2perm') .' AS m,
				'. $this->oDatabase->getT('module_perm') .' AS p
				WHERE m.membership_id = "'. $iType .'" AND p.module_perm_id = m.module_perm_id');

			if ( !$iCnt )
			{
				$aModulePerms = $this->oDatabase->getRows("SELECT module_perm_id, vals FROM ". App::getT('module_perm') ."");
				foreach($aModulePerms as $aPerm)
				{
					$this->oDatabase->insert(App::getT('memb2perm'), array('membership_id' => $iType, 'module_perm_id' => $aPerm['module_perm_id'], 'val' => $aPerm['vals']));
				}
			}

	   		$aRows = $this->oDatabase->getRows('SELECT m.module_perm_id, m.val, p.code FROM
				'. $this->oDatabase->getT('memb2perm') .' AS m,
				'. $this->oDatabase->getT('module_perm') .' AS p
				WHERE m.membership_id = "'. $iType .'" AND p.module_perm_id = m.module_perm_id');

			$content = "<?php\n";
			foreach($aRows as $aRow)
			{
				$aPerms[$iType][$aRow['module_perm_id']] = $aRow['val'];
				$content .= '$this->aPerms[\''. $iType .'\'][\''. $aRow['code'] .'\'] = "'. $aRow['val'] .'";'."\n";
	   		}
	   		$content .= "?>";
	   		$oCache->createCached($content);
	   	}

		$oCache->doRequire();
		$aPerms = $oCache->aPerms;

		return $aPerms;
	}


	function getPermDetails($sPermCode)
	{
		static $aPerms;
		static $aRows;

		$iType = App::getUser('type');

		if ( $iType == '0' || $iType == '1' )
		{
			return 'iamnatio';
		}

		if (!isset($aPerms[$iType]))
	    {
	     	$aPerms = $this->cachePermDetails($iType);
	   	}

		return isset($aPerms[$iType][$sPermCode]) ? $aPerms[$iType][$sPermCode] : $sDef;
	}

	function isStaffAllowed($sPage)
	{
		if ( App::getUser('type') == '0' )
		{
			return true;
		}

		static $aCachePerms = array();		
		
		if (!$aCachePerms)
		{
			$aPerms = $this->getStaffListing();
	
			$aCachePerms = array();
			foreach($aPerms as $iKey => $aPerm)
			{
				$aCachePerms[$aPerm['code']] = $aPerm['val'];
			}
		}

		if (eregi("admin\.", $sPage))
		{
			$aPage = explode('.', $sPage);
			if (count($aPage) > 3)
			{
				$sTempPage = $aPage[0] . '.' . $aPage[1] . '.' . $aPage[2];
				if ( isset($aCachePerms[$sTempPage]) && !$aCachePerms[$sTempPage] )
		        {
					return false;
				}				
			}
		}		
		
		if ( isset($aCachePerms[$sPage]) && !$aCachePerms[$sPage] )
        {
			return false;
		}

		return true;
	}

	function getStaffListing()
	{
		static $aItems;

		if ( $aItems )
		{
			return $aItems;
		}

		$aItems = $this->oDatabase->getRows("SELECT code, val FROM ". App::getT('staff_perm') ."");

		return $aItems;
	}

	/** Get all staff permissions
	 *
	 * @param string $sSect sectino name (if empty - load all permission)
	 * @return array staff permissions
	 */
	function getStaffPermList($sSect = '')
	{
        $oDb = &Database::get();
        /* @var $oDb Database */
        $aRows = $oDb->getRows('SELECT code, val FROM '.App::getT('staff_perm').
        					   ($sSect ? '  WHERE sect = "'.$sSect.'"' : '')  );
        $aPerms = array();
        foreach($aRows as $aRow)
        {
            $aPerms[$aRow['code']] = $aRow['val'];
        }

	    return $aPerms;
	}

	/** Update staff permissions
	 *
	 * @param array $aPerm permissions values array (code=>value)
	 * @return bool true - update succesful, false - error occured
	 */
	function updateStaffPerm($aPerms)
	{
	    $oDb = &Database::get();
	    /* @var $oDb Database */
	    foreach($aPerms as $k=>$v)
	    {
	       $aVals = array('val'=>$v);
	       $oDb->update(App::getT('staff_perm'), $aVals,
	                    'code = "'.$k.'"');
	    }
	    return true;
	}

	/** If staff has selected permission.
	 *
	 * @param string $sCode permissions code
	 */
	function hasStaffPerm($sCode)
	{
		return true;

		if ($this->isAdmin())
	    {
	        return 1;
	    }

	    static $aPerms = null;
	    if (null == $aPerms)
	    {
		    $aPerms = $this->getStaffPermList();
	    }

	    return isset($aPerms[$sCode]) ? $aPerms[$sCode] : 0;
	}

	function checkAccess($sSection, $sRedirectLogicUrl = 'public', $bRedirect = true)
	{
	    $bTrouble = false;
	    if ($sSection == 'music')
	    {
	        if (file_exists(App::getParam('path').'site/public/music.php'))
	        {
	            $bTrouble = true;
	        }
            if (!App::checkUploadParams(App::getParam('Mod_Music.max_song_size')))
            {
                $bTrouble = true;
            }
	    }
	    if (App::getSetting('section_'.$sSection) || $bTrouble)
	    {
	        if ($bRedirect)
	        {
	            App::gotoUrl($sRedirectLogicUrl);
	        }
	        return false;
	    }
	    return true;
	}

	/** Check membership expiration date. Reset to 'normal' if expired.
	 *
	 * @param PhpFox_Mod_Account_ItemAccount $oAcc current user
	 */
    function _checkExpire($oAcc)
    {
		return;
    	
    	//check membership expire
        $aMembershipData = $this->getMembershipData($oAcc->aData['type']);
        
        /*
        This is a temp. fix for the 2038 bug: http://forums.phpfox.com/showthread.php?t=17613
        */
        $oAcc->aData['last_payment'] = str_replace("2038", "2037", $oAcc->aData['last_payment']);

        if ( ($aMembershipData['is_special'] == 0) && ($aMembershipData[' price'] > 0) &&
           (strtotime($oAcc->aData['last_payment'])-time()) < 0)
        {
            $oAcc->aData['type'] = App::getParam('Mod_Account.membership.normal');
            $oAcc->aData['last_payment'] = 0;
            $oAcc->update(array('type','last_payment'));
        }
    }
    
    function checkMyBlockUsers($oCurrUser,$sUser)
	{
		if  (!is_object($oCurrUser))
		{
			return false;
		}
	$iCountusers= $this->oDatabase->getRow("SELECT count(*) FROM `". App::getT('block') ."` WHERE `user1` ='".$oCurrUser->aData['user'] ."' and `user2` ='".$sUser."'");
	
	 return $iCountusers['count(*)'];
		 
	}
}

?>